﻿using System;
using System.Collections.Generic;
using CfgTable;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using NetProtocol.Client;
using NetProtocol.POD;

namespace IQIGame.Onigao.GamePlay
{
    /// <summary>
    /// 类名 : 模块 - 英雄
    /// 作者 : Canyon / 龚阳辉
    /// 日期 : 2024-05-27 14:37
    /// 功能 : 
    /// </summary>
    public class HeroModule : Singleton<HeroModule>, CNetHero
    {
        private HeroModule() { }

        private HeroModuleData heroModuleData => GameDataCenter.PlayerData.hero;

        public void InitModule(PlayerPOD playerPOD)
        {
            HeroModuleData modueData = new HeroModuleData();
            GameDataCenter.PlayerData.hero = modueData;

            var list = playerPOD.heros;
            foreach (var item in list)
            {
                this.UpHeroByPOD(item);
            }
            list.Clear();

            var cfgList = TableCenter.hero.DataList;
            foreach (var cfg in cfgList)
            {
                if (!modueData.ContainsKey(cfg.Id))
                {
                    var heroData = HeroData.ConvertFromCfg(cfg);
                    heroData.skinCid = this.GetSkinId(cfg);
                    modueData.Put(heroData);
                }
            }
        }

        public void ClearModule()
        {
            var data = GameDataCenter.PlayerData.hero;
            GameDataCenter.PlayerData.hero = null;
            data?.Clear();
        }

        #region Net层
        public static CNetHero NetCore => Instance;
        void CNetHero.SC_notifyHeroActive(ISession session, HeroPOD heroPOD)
        {
            this.UpHeroByPOD(heroPOD);
        }

        void CNetHero.SC_notifyHeroAttrs(ISession session, HeroPOD heroPOD)
        {
            this.UpHeroByPOD(heroPOD);
        }

        ISession CNetHero.GetSession()
        {
            return GameServerModule.Instance.CurrSession;
        }
        #endregion

        protected void ChangeData(HeroPOD pod)
        {
            var cfgOne = TableCenter.hero.Get(pod.cid);
            if (cfgOne == null)
            {
                LogGame.LogError($"Not Has CfgHero，The id is ={pod.id}");
                return;
            }
            if (this.heroModuleData.FindHeroDataByCid(pod.cid, out var dCahce))
            {
                dCahce.Sync(pod);
            }
            else
            {
                dCahce = HeroData.ConvertFromPOD(pod);
                this.heroModuleData.Put(dCahce);
            }
            this.heroModuleData.PutIdCid(dCahce);
        }

        public int GetSkinId(CfgHero cfgHero)
        {
            if (cfgHero == null)
                return 0;
            var playData = GameDataCenter.PlayerData;
            bool isMaleRole = playData.isMaleRole;
            if (!isMaleRole && cfgHero.HeroSkinIds2 != null && cfgHero.HeroSkinIds2.Count > 0)
            {
                return cfgHero.HeroSkinIds2[0];
            }
            return cfgHero.HeroSkinIds[0];
        }

        public int GetSkinId(int heroCid)
        {
            var heroData = this.GetHero(heroCid);
            if (heroData == null || heroData.skinCid <= 0)
            {
                var cfgHero = TableCenter.hero.Get(heroCid);
                return this.GetSkinId(cfgHero);
            }
            return heroData.skinCid;
        }

        public CfgHeroSkin GetCfgHeroSkin(int heroCid)
        {
            int skinCid = this.GetSkinId(heroCid);
            return TableCenter.heroSkin.Get(skinCid);
        }

        /// <summary>
        /// 取得所以的英雄列表
        /// </summary>
        public void GetHeros(int tab, List<HeroData> list, Comparison<HeroData> sortFunc = null)
        {
            System.Func<HeroData, bool> func = heroData =>
            {
                var cfg = heroData.cfgData;
                return !cfg.IsHide && (tab == 0 || tab == cfg.HeroClass);
            };
            var result = heroModuleData.GetSortHeros(func, sortFunc);
            list.AddRange(result);
        }

        /// <summary>
        /// 取得自己拥有的英雄列表
        /// </summary>
        public List<HeroData> GetOwnHeros(int tab, Comparison<HeroData> sortFunc = null)
        {
            System.Func<HeroData, bool> func = heroData =>
            {
                var cfg = heroData.cfgData;
                return !cfg.IsHide && heroData.isGeted && (tab == 0 || tab == cfg.HeroClass);
            };
            var result = heroModuleData.GetSortHeros(func, sortFunc);
            return result;
        }

        public HeroData GetHero(int cid)
        {
            return this.heroModuleData.FindHeroDataByCid(cid, out HeroData hero) ? hero : null;
        }

        public string GetHeroName(HeroData data)
        {
            CfgSoul cfgSoul = data.cfgSoul;
            EM_SoulType em = (EM_SoulType)cfgSoul.Type;
            if (em == EM_SoulType.MainRole)
            {
                return GameDataCenter.PlayerData.playerName;
            }
            return data.cfgData.Name;
        }

        public int GetNextExp(int heroLev)
        {
            var cfg = TableCenter.heroLevel.Get(heroLev);
            if (cfg == null)
            {
                return 0;
            }
            return cfg.NextEXP;
        }

        public List<UD_HereFeature> GetHeroFeatureCfgStars(int heroCid, int heroStar)
        {
            List<UD_HereFeature> ret = new List<UD_HereFeature>();
            var mapHeroId = TableCenter.heroStar.heroIdStarMap;
            if (mapHeroId.TryGetValue(heroCid, out var mapStar))
            {
                CfgHeroStar _cfgStar = TableCenter.heroStar.Get(mapStar[heroStar]);
                int cnt = mapStar.Count;
                CfgHeroStar _hStar = null;
                for (int i = 0; i < cnt; i++)
                {
                    _hStar = TableCenter.heroStar.Get(mapStar[i]);
                    if (_hStar != null && _hStar.IsShowFeature)
                    {
                        UD_HereFeature data = UD_HereFeature.NewFromPool();
                        data.Sync(_cfgStar.BigStar, _hStar.Id);
                        ret.Add(data);
                    }
                }
            }
            return ret;
        }

        public void UpHeroByPOD(HeroPOD pod)
        {
            this.ChangeData(pod);
            PODPool<HeroPOD>.Put(pod);
        }
    }
}
